home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / elk-2_0.lha / elk-2.0 / contrib / zelk / src-zlib / wildmat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-17  |  3.1 KB  |  141 lines

  1. /*
  2. **  Do shell-style pattern matching for ?, \, [], and * characters.
  3. **  Might not be robust in face of malformed patterns; e.g., "foo[a-"
  4. **  could cause a segmentation violation.  It is 8bit clean.
  5. **
  6. **  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
  7. **  Rich $alz is now <rsalz@bbn.com>.
  8. **  Special thanks to Lars Mathiesen <thorinn@diku.dk> for the ABORT code.
  9. **  This can greatly speed up failing wildcard patterns.  For example:
  10. **    pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
  11. **    text 1:     -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
  12. **    text 2:     -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1
  13. **  Text 1 matches with 51 calls, while text 2 fails with 54 calls.  Without
  14. **  the ABORT, then it takes 22310 calls to fail.  Ugh.
  15. */
  16.  
  17. #define TRUE        1
  18. #define FALSE        0
  19. #define ABORT        -1
  20.  
  21. #define NEGATE_CLASS    '^'
  22.  
  23. /* Forward declaration. */
  24. static int    DoMatch();
  25.  
  26. /*
  27. **  See if the text matches the p, which has an implied leading asterisk.
  28. */
  29. static int
  30. Star(text, p)
  31.     register char    *text;
  32.     register char    *p;
  33. {
  34.     register int    ret;
  35.  
  36.     do
  37.     ret = DoMatch(text++, p);
  38.     while (ret == FALSE);
  39.     return ret;
  40. }
  41.  
  42.  
  43. /*
  44. **  Match text and p, return TRUE, FALSE, or ABORT.
  45. */
  46. static int
  47. DoMatch(text, p)
  48.     register char    *text;
  49.     register char    *p;
  50. {
  51.     register int      last;
  52.     register int      matched;
  53.     register int      reverse;
  54.  
  55.     for ( ; *p; text++, p++) {
  56.     if (*text == '\0' && *p != '*')
  57.         return ABORT;
  58.     switch (*p) {
  59.     case '\\':
  60.         /* Literal match with following character. */
  61.         p++;
  62.         /* FALLTHROUGH */
  63.     default:
  64.         if (*text != *p)
  65.         return FALSE;
  66.         continue;
  67.     case '?':
  68.         /* Match anything. */
  69.         continue;
  70.     case '*':
  71.         /* Trailing star matches everything. */
  72.         return *++p ? Star(text, p) : TRUE;
  73.     case '[':
  74.         if (reverse = p[1] == NEGATE_CLASS)
  75.         /* Inverted character class. */
  76.         p++;
  77.         for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
  78.         /* This next line requires a good C compiler. */
  79.         if (*p == '-' ? *text <= *++p && *text >= last : *text == *p)
  80.             matched = TRUE;
  81.         if (matched == reverse)
  82.         return FALSE;
  83.         continue;
  84.     }
  85.     }
  86.  
  87.     return *text == '\0';
  88. }
  89.  
  90.  
  91. /*
  92. **  User-level routine.  Returns TRUE or FALSE.
  93. */
  94. int
  95. wildmat(text, p)
  96.     char    *text;
  97.     char    *p;
  98. {
  99.     return DoMatch(text, p) == TRUE;
  100. }
  101.  
  102.  
  103.  
  104. #ifdef    TEST
  105. #include <stdio.h>
  106.  
  107. /* Yes, we use gets not fgets.  Sue me. */
  108. extern char    *gets();
  109.  
  110.  
  111. main()
  112. {
  113.     char     p[80];
  114.     char     text[80];
  115.  
  116.     printf("Wildmat tester.  Enter pattern, then strings to test.\n");
  117.     printf("A blank line gets prompts for a new pattern; a blank pattern\n");
  118.     printf("exits the program.\n\n");
  119.  
  120.     for ( ; ; ) {
  121.     printf("Enter pattern:  ");
  122.     (void)fflush(stdout);
  123.     if (gets(pattern) == NULL || pattern[0] == '\n')
  124.         break;
  125.     for ( ; ; ) {
  126.         printf("Enter text:  ");
  127.         (void)fflush(stdout);
  128.         if (gets(text) == NULL)
  129.         exit(0);
  130.         if (text[0] == '\0')
  131.         /* Blank line; go back and get a new pattern. */
  132.         break;
  133.         printf("      %s\n", wildmat(text, pattern) ? "YES" : "NO");
  134.     }
  135.     }
  136.  
  137.     exit(0);
  138.     /* NOTREACHED */
  139. }
  140. #endif    /* TEST */
  141.